package service

import (
	"core/auth"
	"core/coreentity"
	"core/coreqto"
	"core/coreservice"
	"core/corestruct"
	"core/coreutil"
	"core/datetime"
	"core/myerrors"
	"fmt"
	"gorm.io/gorm"
	"ht/api/htuser/data"

	"time"
)

type mainService struct {
}

// Page 按机构用户分页
func (p *mainService) Page(mm *data.HtUserQto, ctx *corestruct.HttpContext) (*corestruct.Page[data.HtUserDto], error) {
	var db = ctx.DB
	db = db.Model(&coreentity.HtUserDept{}).
		Select("ur.*,HtUserDept.state,dt.name as crt_dname").
		Joins("inner join htuser ur on HtUserDept.Htdept_id=?  and HtUserDept.Htuser_id=ur.id", mm.HtdeptId).
		Joins("inner join htdept dt on HtUserDept.Htdept_id=dt.id", "")
	if mm.Id > 0 {
		db = db.Where("HtUserDept.Htuser_id=?", mm.Id)
	} else {
		if "" != mm.State {
			db = db.Where("HtUserDept.state=?", mm.State)
		}
		if "" != mm.Key {
			var likeV = "%" + mm.Key + "%"
			db = db.Where("ur.name like ? or ur.mobile like ?", likeV, likeV)
		}
	}
	var svr = &coreservice.PageService[data.HtUserDto]{}
	r, err := svr.Page(&mm.BasePageQto, ctx, db)
	if err != nil {
		return nil, myerrors.NewByErr(err)
	}

	var uids = make([]int64, 0)
	for index := range r.Records {
		var v = &r.Records[index]
		v.CrtDid = mm.HtdeptId
		uids = append(uids, v.Id)
		v.RoleList = make([]corestruct.IdNameDto, 0)
	}
	//获取角色
	lrole, err := coreservice.HtUserRoleservice.GetRoles(uids, mm.HtdeptId, ctx)
	if err != nil {
		return nil, myerrors.NewByErr(err)
	}
	for index := range r.Records {
		var v = &r.Records[index]
		var index = coreutil.ArrayUtil.IndexOf(lrole, func(ele interface{}, index int) bool {
			return ele.(corestruct.IdNameAttrDto).Id1 == v.Id
		})
		if index > 0 {
			var pmrole = &lrole[index]
			v.RoleList = append(v.RoleList, corestruct.IdNameDto{
				Id:   pmrole.Id,
				Name: pmrole.Name})
		}
	}
	return r, nil
}

// Detail 按机构用户详情
func (p *mainService) Detail(mm *data.HtUserDetailQto, ctx *corestruct.HttpContext) (*data.HtUserDto, error) {
	var qto = &data.HtUserQto{
		BasePageQto: coreqto.BasePageQto{
			Id:       mm.Id,
			Page:     1,
			PageSize: 1,
		},
		HtdeptId: mm.HtdeptId,
	}
	var r, err = p.Page(qto, ctx)
	if err != nil {
		return nil, err
	}
	if r.TotalRow == 0 {
		return nil, myerrors.NewDataNotExist()
	}
	return &r.Records[0], nil
}

// InsertInit 插入初始化
func (p *mainService) InsertInit(mm *corestruct.IdModel, ctx *corestruct.HttpContext) (*data.HtUserDto, error) {
	var r = &data.HtUserDto{
		Id:       coreutil.IdUtil.GetId(),
		Ename:    "",
		Name:     "",
		EditPwd:  false,
		Pwd:      "",
		Sex:      "",
		Birthday: datetime.MyTime{},
		Zw:       "",
		Email:    "",
		Mobile:   "",
		Address:  "",
		Memo:     "",
		Url:      "",
		CrtDt:    datetime.MyTime{},
		CrtUid:   0,
		CrtDid:   mm.Id,
		EdtDt:    datetime.MyTime{},
		CrtUname: "",
		CrtDname: "",
		State:    "启用",
		RoleList: make([]corestruct.IdNameDto, 0),
	}
	var db = ctx.DB
	r.CrtDname = coreservice.BaseService.GetName(&coreentity.HtDept{Id: r.CrtDid}, db)

	return r, nil
}

// CheckExistByEname
// 检查用户账号是不是存在
func (p *mainService) CheckExistByEname(ename string, ctx *corestruct.HttpContext) (bool, error) {
	var m = &coreentity.HtUser{Ename: ename}
	tx := ctx.DB.Where(m).
		Select("id").
		//Omit("name").
		Find(m)
	if tx.Error != nil {
		return false, tx.Error
	}
	return m.Id > 0, nil
}

// Insert
// 插入用户
func (p *mainService) Insert(mm *data.HtUserDto, ctx *corestruct.HttpContext) (int64, error) {
	bExist, myerr := p.CheckExistByEname(mm.Ename, ctx)
	if myerr != nil {
		return 0, myerr
	}
	if bExist == true {
		return 0, myerrors.New("账号重复")
	}

	var db = ctx.DB
	var su = ctx.Session

	err := db.Transaction(func(tx *gorm.DB) error {
		mm.Pwd = auth.CreatePwd(mm.Ename, mm.Pwd)
		tx2 := coreservice.BaseService.InsertByDto(mm, &coreentity.HtUser{}, tx)
		if tx2.Error != nil {
			return tx2.Error
		}
		var mud = &coreentity.HtUserDept{
			Id:       coreutil.IdUtil.GetId(),
			HtuserId: mm.Id,
			HtdeptId: mm.CrtDid,
			State:    "启用",
			CrtDt:    datetime.MyTime(time.Now()),
			CrtUid:   su.CrtUid,
			CrtDid:   su.HtdeptId,
			EdtDt:    datetime.MyTime(time.Now()),
			EdtUid:   su.CrtUid,
			Gid:      coreutil.IdUtil.UuidStr(),
			Deleted:  0,
		}
		tx2 = tx.Create(mud)
		if tx2.Error != nil {
			return tx2.Error
		}
		for _, role := range mm.RoleList {
			var mur = &coreentity.HtUserRole{
				Id:       coreutil.IdUtil.GetId(),
				HtuserId: mm.Id,
				HtdeptId: mm.CrtDid,
				HtroleId: role.Id,
				CrtDt:    datetime.MyTime(time.Now()),
				CrtUid:   su.CrtUid,
				CrtDid:   su.HtdeptId,
				EdtDt:    datetime.MyTime(time.Now()),
				EdtUid:   su.CrtUid,
				Gid:      coreutil.IdUtil.UuidStr(),
				Deleted:  0,
			}
			tx2 = tx.Create(mur)
			if tx2.Error != nil {
				return tx2.Error
			}
		}

		return nil
	})

	if err != nil {
		return 0, myerrors.NewByErr(err)
	}

	return mm.Id, nil
}

// Update
// 修改用户
func (p *mainService) Update(mm *data.HtUserDto, ctx *corestruct.HttpContext) (int64, error) {
	var db = ctx.DB
	var su = ctx.Session

	var m = &coreentity.HtUser{
		Id: mm.Id,
	}
	var err = db.Find(m).Error
	if err != nil {
		return 0, myerrors.NewByErr(err)
	}

	if m.Ename != mm.Ename {
		bExist, myerr := p.CheckExistByEname(mm.Ename, ctx)
		if myerr != nil {
			return 0, myerr
		}
		if bExist == true {
			return 0, myerrors.New("账号重复")
		}
	}

	lrole, err := coreservice.HtUserRoleservice.GetRoles([]int64{mm.Id}, mm.CrtDid, ctx)
	if err != nil {
		return 0, err
	}

	err = db.Transaction(func(tx *gorm.DB) error {

		if mm.EditPwd {
			mm.Pwd = auth.CreatePwd(mm.Ename, mm.Pwd)
		} else {
			mm.Pwd = m.Pwd
		}
		tx2 := coreservice.BaseService.UpdateByDto(mm, m, db)
		if tx2.Error != nil {
			return tx2.Error
		}

		if tx2.Error != nil {
			return tx2.Error
		}

		for _, role := range mm.RoleList {
			var mold = coreutil.ArrayUtil.Find(lrole, func(ele interface{}, index int) bool {
				return ele.(corestruct.IdNameAttrDto).Id == role.Id
			})
			if mold != nil {
				continue
			}
			var mur = &coreentity.HtUserRole{
				Id:       coreutil.IdUtil.GetId(),
				HtuserId: mm.Id,
				HtdeptId: mm.CrtUid,
				HtroleId: role.Id,
				CrtDt:    datetime.MyTime{},
				CrtUid:   su.CrtUid,
				CrtDid:   su.HtdeptId,
				EdtDt:    datetime.MyTime{},
				EdtUid:   su.CrtUid,
				Gid:      coreutil.IdUtil.UuidStr(),
				Deleted:  0,
			}
			tx2 = tx.Create(mur)
			if tx2.Error != nil {
				return tx2.Error
			}
		}
		for _, role := range lrole {
			var mold = coreutil.ArrayUtil.Find(mm.RoleList, func(ele interface{}, index int) bool {
				return ele.(corestruct.IdNameDto).Id == role.Id
			})
			if mold != nil {
				continue
			}
			tx2 = tx.Delete(role)
			if tx2.Error != nil {
				return tx2.Error
			}
		}

		return nil
	})

	if err != nil {
		return 0, myerrors.NewByErr(err)
	}
	_ = coreservice.BaseService.DeleteCacheById(mm.Id)
	return mm.Id, nil
}

// Qy
// 启用
func (p *mainService) Qy(mm *corestruct.IdModel, ctx *corestruct.HttpContext) (int64, error) {
	var db = ctx.DB
	var su = ctx.Session

	var m = &coreentity.HtUserDept{HtuserId: mm.Id, HtdeptId: su.HtdeptId}
	var tx = db.Model(m).Where(m).Select("id,state").Find(m)
	if tx.Error != nil {
		return 0, tx.Error
	}
	if "停用" == m.State {
		m.State = "启用"
		m.EdtDt = datetime.MyTime(time.Now())
		m.EdtUid = su.CrtUid
		tx = tx.Updates(m)
		if tx.Error != nil {
			return 0, tx.Error
		}
		var ModelName = coreservice.BaseService.GetName(&coreentity.HtUser{}, db)
		ctx.LogMemo = fmt.Sprintf("启用用户 %s", ModelName)
		return mm.Id, nil
	}
	return 0, nil
}

// Ty
// 停用
func (p *mainService) Ty(mm *corestruct.IdModel, ctx *corestruct.HttpContext) (int64, error) {
	var db = ctx.DB
	var su = ctx.Session

	var m = &coreentity.HtUserDept{HtuserId: mm.Id, HtdeptId: su.HtdeptId}
	var tx = db.Model(m).Where(m).Select("id,name,state").Find(m)
	if tx.Error != nil {
		return 0, tx.Error
	}
	if "启用" == m.State {
		m.State = "停用"
		m.EdtDt = datetime.MyTime(time.Now())
		m.EdtUid = su.CrtUid
		tx = tx.Updates(m)
		if tx.Error != nil {
			return 0, tx.Error
		}
		var ModelName = coreservice.BaseService.GetName(&coreentity.HtUser{}, db)
		ctx.LogMemo = fmt.Sprintf("停用用户 %s", ModelName)
		return mm.Id, nil
	}
	return 0, nil
}

var (
	MainService = &mainService{}
)
